import type { RouteLocationNormalized, RouteLocationNormalizedLoaded, RouteRecordNormalized, RouteRecordRaw, Router } from 'vue-router';
import { createRouter, createWebHashHistory } from 'vue-router';
import { clone, isUrl, reject } from 'element-plus-extension/es/shared';

const modules = import.meta.glob('../views/**/*.{vue,tsx}');

/** Layout */
export const Layout = () => import('@/layout/index.vue');

/** 空白路由导航 */
export const genBankLayout = () => {
  return () => import('@/layout/components/bank-view/index.vue');
};

export const getRawRoute = (route: RouteLocationNormalized): RouteLocationNormalized => {
  if (!route) return route;
  const { matched, ...opt } = route;
  return {
    ...opt,
    matched: (matched
      ? matched.map((item) => ({
          meta: item.meta,
          name: item.name,
          path: item.path
        }))
      : undefined) as RouteRecordNormalized[]
  };
};

// 前端控制路由生成
export const generateRoutesByFrontEnd = (routes: RouteRecordRaw[], keys: string[], basePath = '/'): RouteRecordRaw[] => {
  const res: RouteRecordRaw[] = [];

  for (const route of routes) {
    const meta = route.meta ?? {};
    // skip some route
    if (meta.hidden && !meta.canTo) {
      continue;
    }
    let data: RouteRecordRaw | null = null;
    let onlyOneChild: Nullable<string> = null;
    if (route.children && route.children.length === 1 && !meta.alwaysShow) {
      onlyOneChild = (
        isUrl(route.children[0].path) ? route.children[0].path : pathResolve(pathResolve(basePath, route.path), route.children[0].path)
      ) as string;
    }

    /** 根据路由路径权限过滤 */
    for (const item of keys) {
      // 通过路径去匹配
      if (isUrl(item) && (onlyOneChild === item || route.path === item)) {
        data = Object.assign({}, route);
      } else {
        const routePath = (onlyOneChild ?? pathResolve(basePath, route.path)).trim();
        if (routePath === item || meta.followRoute === item) {
          data = Object.assign({}, route);
        }
      }
    }
    if (!keys.length) {
      data = route;
    }
    // recursive child routes
    if (route.children && data) {
      data.children = generateRoutesByFrontEnd(route.children, keys, pathResolve(basePath, data.path));
    }
    if (data) {
      res.push(data as RouteRecordRaw);
    }
  }
  return res;
};

// 后端控制路由生成
export const generateRoutesByServer = (routes: Array<RouteRecordRaw>): RouteRecordRaw[] => {
  const res: RouteRecordRaw[] = [];
  for (const route of routes) {
    const data: Partial<RouteRecordRaw> = {
      path: route.path,
      name: route.name,
      redirect: route.redirect,
      meta: route.meta
    };
    if (route.component) {
      const comModule = modules[`../${route.component}.vue`] || modules[`../${route.component}.tsx`];
      const component = route.component as unknown as string;
      if (!comModule && !component.includes('#')) {
        console.error(`未找到${route.component}.vue文件或${route.component}.tsx文件，请创建`);
      } else {
        // 动态加载路由文件，可根据实际情况进行自定义逻辑
        data.component = component === '#' ? Layout : component.includes('##') ? genBankLayout() : comModule;
      }
    }
    // recursive child routes
    if (route.children) {
      data.children = generateRoutesByServer(route.children);
    }
    res.push(data as RouteRecordRaw);
  }
  return res;
};

export const pathResolve = (parentPath: string, path: string) => {
  if (isUrl(path)) return path;
  const childPath = path.startsWith('/') || !path ? path : `/${path}`;
  return `${parentPath}${childPath}`.replace(/\/\//g, '/').trim();
};

// 路由降级
export const flatMultiLevelRoutes = (routes: RouteRecordRaw[]) => {
  const modules: RouteRecordRaw[] = clone(routes, true);
  for (const route of modules) {
    if (!isMultipleRoute(route)) {
      continue;
    }
    promoteRouteLevel(route);
  }
  return modules;
};

// 层级是否大于2
const isMultipleRoute = (route: RouteRecordRaw) => {
  if (!route || !Reflect.has(route, 'children') || !route.children?.length) {
    return false;
  }

  const children = route.children;

  let flag = false;
  for (const child of children) {
    if (child.children?.length) {
      flag = true;
      break;
    }
  }
  return flag;
};

// 生成二级路由
const promoteRouteLevel = (route: RouteRecordRaw) => {
  let router: Router | null = createRouter({
    routes: [route as RouteRecordRaw],
    history: createWebHashHistory()
  });

  const routes = router.getRoutes();
  addToChildren(routes, route.children || [], route);
  router = null;
  if (route.children) {
    route.children = route.children.map((item) => reject(item, 'children')) as RouteRecordRaw[];
  }
};

// 添加所有子菜单
const addToChildren = (routes: RouteRecordNormalized[], children: RouteRecordRaw[], routeModule: RouteRecordRaw) => {
  for (const child of children) {
    const route = routes.find((item) => item.name === child.name);
    if (!route) {
      continue;
    }
    routeModule.children = routeModule.children || [];
    if (!routeModule.children.some((item) => item.name === route.name)) {
      routeModule.children?.push(route as unknown as RouteRecordRaw);
    }
    if (child.children?.length) {
      addToChildren(routes, child.children, routeModule);
    }
  }
};

export const filterAffixTags = (routes: RouteRecordRaw[], parentPath = '') => {
  let tags: RouteLocationNormalizedLoaded[] = [];
  routes.forEach((route) => {
    const meta = route.meta ?? {};
    const tagPath = pathResolve(parentPath, route.path);
    if (meta?.affix) {
      tags.push({
        ...route,
        path: tagPath,
        fullPath: tagPath
      } as unknown as RouteLocationNormalizedLoaded);
    }
    if (route.children) {
      const tempTags: RouteLocationNormalizedLoaded[] = filterAffixTags(route.children, tagPath);
      if (tempTags.length >= 1) {
        tags = [...tags, ...tempTags];
      }
    }
  });

  return tags;
};
